using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.IO;

namespace CommandPatternApp
{
    public class TextEditor
    {
        private CmdFactory _factory;
        private UndoCmd _undoCmd;
        private TextBox _textBox;
        private OpenFileDialog _openFileDlg;
        private string _filePath;

        public TextEditor(TextBox textBox)
        {
            _textBox = textBox;
            _undoCmd = null;
            _openFileDlg = new OpenFileDialog();
            this._textBox.KeyDown += 
                new System.Windows.Forms.KeyEventHandler(this.TextBoxKeyDown);
        }

        #region Properties
        public int SelectionStart
        {
            get { return _textBox.SelectionStart; }
        }

        public string SelectedText
        {
            get { return _textBox.SelectedText; }
        }

        public CmdFactory CmdFactory
        {
            set { _factory = value; }
        }

        public UndoCmd UndoCmd
        {
            set { _undoCmd = value; }
        }
        #endregion

        #region Commands execution
        public void OpenFile()
        {
            _openFileDlg.Filter = "Text Files (*.txt)|*.txt";
            DialogResult result = _openFileDlg.ShowDialog();
            if (result == DialogResult.OK)
            {
                _textBox.Clear();
                _filePath = _openFileDlg.FileName;
                StreamReader sd = new StreamReader(_filePath);
                _textBox.Text = sd.ReadToEnd();
                sd.Close();
            }
        }

        public void SaveFile()
        {
            if (_filePath == null) return;
            StreamWriter sw = new StreamWriter(_filePath);
            sw.Write(_textBox.Text);
            sw.Close();
        }

        public void Copy()
        {
            _textBox.Copy();
        }

        public void Cut(CutCmd cmd)
        {
            _textBox.Cut();
            _undoCmd.Push(cmd);
        }

        public void UndoCut(int selStart, string selText)
        {
            _textBox.Select(selStart, 0);
            _textBox.Paste(selText);
        }

        public void Paste(PasteCmd cmd)
        {
            _textBox.Paste();
            _undoCmd.Push(cmd);
        }

        public void UndoPaste(int selStart, string selText, int pasteLen)
        {
            _textBox.Select(selStart, pasteLen);
            _textBox.Paste("");         // erase pasted text
            _textBox.Paste(selText);    // restore text being overwritten 
            _textBox.SelectionLength = 0;
        }

        #endregion

        #region Shortcut keys handling
        private void TextBoxKeyDown(object sender, KeyEventArgs e)
        {
            // ctl-v pressed. Create a paste command for undoing paste.
            if (e.Modifiers == Keys.Control && e.KeyCode == Keys.V)
            {
                PasteCmd cmd = _factory.PasteCmd();
                _undoCmd.Push(cmd);
            }
            // ctl-x pressed. Create a cut command for undoing cut.
            if (e.Modifiers == Keys.Control && e.KeyCode == Keys.X)
            {
                CutCmd cmd = _factory.CutCmd();
                _undoCmd.Push(cmd);
            }
                // ctl-z pressed, undo most recent undoable command.
            else if (e.Modifiers == Keys.Control && e.KeyCode == Keys.Z)
            {
                _undoCmd.Execute();
            }
        }
        #endregion
    }
}
